<!--
   封装了基本增删改查的表格页面
   以数据驱动整体页面各表单以及各模态框的内容
   基础参数
   controller
   add
   edit
-->
<template>
  <el-container v-loading="loading">
    <el-header class="myHeader">
      <div class="handle-box" >
        <div class="topActionBar">
          <el-col v-if="page_data.actionBar" :xs="24" :sm="15" :md="17" :lg="18" :xl="18">
            <template v-for="b in page_data.actionBar.buttons">
              <el-button v-if="b.type == 'add'" :size="b.size || 'small'" icon="el-icon-plus" class="button-add" @click="add_dialog_visible = true">{{b.name}}</el-button>
              <el-button v-if="b.type == 'batch_remove'" :size="b.size || 'small'" icon="el-icon-delete" class="button-del el-button--danger" @click="delAllBtnHandle">{{b.name}}</el-button>
              <el-button v-if="b.type == 'custom'" :icon="b.icon || null" :class="b.class" :size="b.size || 'small'" :type="b.type" @click="eventDispatcher(b.eventName)">
                {{b.name}}
              </el-button>
            </template>
            <el-button v-if="page_data.searchInputs" @click="moreSearch = !moreSearch" icon="el-icon-search" size="small">更多搜索</el-button>
          </el-col>
          <el-col v-if="page_data.searchInputs" :xs="24" :sm="9" :md="7" :lg="6" :xl="6">
            <el-input placeholder="筛选关键词" class="w100 search-input hidden-xs-only" :keyup.enter="searchHandle" @blur="searchHandle" v-model="search.value">
              <el-select v-model="search.select" slot="prepend" placeholder="请选择">
                <template v-for="i in page_data.searchInputs">
                    <el-option v-if="i.type === 'text'" :label="i.title" :value="i.name"></el-option>
                </template>
              </el-select>
              <i slot="suffix" class="el-input__icon el-icon-search"></i>
            </el-input>
          </el-col>
        </div>
        <el-col :xs="1" :sm="6" :md="6" :lg="6" :xl="6">&nbsp;</el-col>
        <el-col v-if="page_data.searchInputs" v-show="moreSearch" class="moreSearch" :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
          <input-group :data="page_data.searchInputs"></input-group>
          <div style="text-align: center">
            <el-button type="primary" @click="searchHandle(false)">查询</el-button>
            <el-button @click="moreSearchClear">清空</el-button>
          </div>
        </el-col>
      </div>
    </el-header>
    <el-main>
      <!-- select-on-indeterminate=false 部分行被选中时点击全选按钮取消选择所有行-->
      <el-table
        :data="table_data"
        ref="multipleTable"
        height="500"
        style="width: 100%"
        :select-on-indeterminate="false"
        :row-class-name="tableRowClassName"
        @selection-change="selectionChangeHandle"
        @sort-change="sortHandle"
        @filter-change="filterHandle"
        @row-dblclick="detailBtnHandle"
        border>
        <el-table-column
          fixed
          type="selection"
          width="55">
        </el-table-column>
        <slot v-if="page_data.columns.scene === 'custom' ? true : false"></slot>
        <template v-if="page_data.columns.scene === 'custom' ? false : (page_data.columns.columns ? true : false)" >
          <el-table-column
            v-for="(c, index) in page_data.columns.columns"
            :key="index"
            :fixed="c.fixed || false"
            :prop="c.column"
            :label="c.label"
            :width="c.width || 'auto'"
            :sortable="c.sortable ? 'custom' : false"
            :column-key="c.column"
            :filter-multiple="Object.keys(c).indexOf('filters') >= 0 ? (c.filters.multiple || false) : null"
            :filters="Object.keys(c).indexOf('filters') >= 0 ? (c.filters.species || null) : null"
          >
          </el-table-column>
        </template>
        <template v-if="page_data.columns.scene === 'custom' ? false : (page_data.columns.buttons ? true : false)">
          <el-table-column align="center" fixed="right" label="操作" :width="220">
              <template slot-scope="scope">
                  <template v-for="b in page_data.columns.buttons" >
                    <el-button v-if="b.type == 'detail'" :class="b.class" :size="b.size || 'mini'"  @click="detailBtnHandle(scope.row)">
                      {{b.name}}
                    </el-button>
                    <el-button v-if="b.type == 'edit'" :class="b.class" :size="b.size || 'mini'"  type="primary" @click="editBtnHandle(scope.$index, scope.row)">
                      {{b.name}}
                    </el-button>
                    <el-button v-if="b.type == 'remove'" :class="b.class" :size="b.size || 'mini'" type="danger"  @click="deleteBtnHandle(scope.$index, scope.row)">
                      {{b.name}}
                    </el-button>
                  </template>
              </template>
          </el-table-column>
        </template>
      </el-table>

       <my-dialog
         v-if="page_data.detailInputs && Object.keys(page_data.detailInputs).length"
         :title="page_data.detailInputs.title || '详情'"
         :remoteUrl="page_data.detailInputs.remoteUrl"
         :wide="page_data.detailInputs.wide || true"
         :open.sync="detail_dialog_visible" :footerBtn="false">
         <input-group :data="page_data.detailInputs.inputs || []" ref="inputsRef"/>
       </my-dialog>

       <my-dialog
         v-if="page_data.addInputs && Object.keys(page_data.addInputs).length"
         :title="page_data.addInputs.title || '新增'"
         :wide="page_data.addInputs.wide || false"
         :width="!page_data.addInputs.wide ? page_data.addInputs.width : '40%'"
         :height="!page_data.addInputs.wide ? page_data.addInputs.height : 30"
         :open.sync="add_dialog_visible"
         @ok="addOkHandler" @off="addOffDialogHandler"
       >
          <input-group :data="page_data.addInputs.inputs || []" ref="inputsRef"/>
      </my-dialog>
      <my-dialog
        v-if="page_data.editInputs && Object.keys(page_data.editInputs).length"
        :title="page_data.editInputs.title || '修改'"
        :wide="page_data.editInputs.wide || false"
        :width="!page_data.editInputs.wide ? page_data.editInputs.width : '40%'"
        :height="!page_data.editInputs.wide ? page_data.editInputs.height : 30"
        :open.sync="edit_dialog_visible"
        @ok="editOkHandler" @off="addOffDialogHandler"
      >
        <input-group :data="page_data.editInputs.inputs || []" ref="inputsRef"></input-group>
      </my-dialog>
    </el-main>
    <el-footer>
      <div class="pagination">
        <el-pagination @current-change="currentChangeHandle" @size-change="sizeChangeHandle" layout="sizes,prev, pager, next,jumper,total" :page-size="pageSize" :page-sizes="pageSizes" :total="total">
        </el-pagination>
      </div>
    </el-footer>
  </el-container>
</template>

<script>
import { get } from '@/utils/ajax.js'
import MyDialog from '@/components/common/MyDialog.vue'
import InputGroup from '@/components/common/InputGroup.vue'
import layer from 'layer'

export default {
  name: 'BaseTable',
  props: {
    controller: String,
    requestPrefix: String
  },
  components: {
    MyDialog,
    InputGroup
  },
  data() {
    return {
      search: {},
      moreSearch: false,
      loading: true,
      table_data: [],
      page_data: {},
      filters: {},
      sort: {},
      controller_: this.controller,
      request_prefix: this.requestPrefix,
      detail_dialog_visible: false,
      add_dialog_visible: false,
      edit_dialog_visible: false,
      multiple_selection: [],
      cur_page: 1,
      pageSize: 10,
      total: 1,
      pageSizes: [10, 20, 50, 100]
    }
  },
  methods: {
    moreSearchClear() { // 更多搜索清除事件处理
      var $this = this
      if (!$this.page_data.searchInputs) return
      $this.page_data.searchInputs.forEach(input => {
        $this.$set(input, 'value', '')
      })
    },
    searchHandle(sync = true) { // 页面查询事件处理 sync 是否同步到作用域
      var $this = this
      if (sync) {
        this.moreSearchClear()
        $this.page_data.searchInputs.forEach(input => {
          if (!input.value && $this.search.select === input.name) {
            $this.$set(input, 'value', $this.search.value)
          }
        })
      }
      this.getData()
    },
    getQueryParameter(voParam) { // 再包装各查询参数返回后台所需查询参数对象
      var order = { 'ascending': 'asc', 'descending': 'desc' }
      var vo = {}
      if (voParam && this.page_data.searchInputs) {
        this.page_data.searchInputs.forEach(input => {
          if (input.value && input.value.length > 0) {
            var type = input.type
            if (type === 'sedate' || type === 'sedatetime') {
              vo[input.name + 'Start'] = input.value[0]
              vo[input.name + 'End'] = input.value[1]
            } else {
              vo[input.name] = input.value
            }
          }
        })
      }
      for (var key in this.filters) {
        if (this.filters[key].length === 1) {
          vo[key] = this.filters[key][0]
        }
        if (this.filters[key].length > 1) {
          vo[key] = this.filters[key]
        }
      }
      var json = {
        pageCur: this.cur_page,
        pageSize: this.pageSize,
        vo: vo
      }
      if (this.sort.prop) json.sortColumn = this.sort.prop
      if (this.sort.order && order[this.sort.order]) json.order = order[this.sort.order]
      return json
    },
    getData(voParam = true) { // 请求后台获取列表数据
      var $this = this
      const queryParameter = $this.getQueryParameter(voParam)
      console.log(queryParameter)
      setTimeout(() => {
        $this.loading = false
        var url = $this.request_prefix + $this.controller_
        console.log('request getdata url: ' + url)
        get({ url: url }, (res) => {
          $this.table_data = res
          $this.total = Math.ceil($this.table_data.length / $this.pageSize)
        })
      }, 500)
    },
    tableRowClassName(param) { // 渲染表格时修改某一行的样式
      let className = ''
      this.multiple_selection.forEach((val) => {
        if (val.id === param.row.id) {
          className = 'pitch-on'
          return false
        }
      })
      return className
    },
    eventDispatcher() { // 事件分配器  第一个参数必须为实际事件名
      var len = arguments.length
      if (len < 1) return
      var funName = arguments[0]
      if (!funName || funName === undefined) {
        return
      }
      var parms = []
      for (var i = 1; i < len; i++) {
        parms.push(arguments[i])
      }
      this.$emit.apply(this, parms)
      // return this[funName].apply(this, parms);
    },
    addOkHandler() { // 添加模态框保存事件处理
      var res = this.$refs.inputsRef.allInputVerify()
      if (!res) {
        layer.msg('填写的信息有误')
        return
      }
      var inputs = this.page_data.addInputs.inputs
      console.log('验证通过')
      console.log(inputs)
      // 请求后台保存后
      this.$emit('addSaveAfterHandler', inputs)
    },
    addOffDialogHandler() { // 关闭模态框的时候初始化所有表单验证
      this.$refs.inputsRef.allInputInitVerify()
    },
    deletes(ids) { // 删除统一方法
      this.$confirm('此操作将永久删除该记录, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$message({
          type: 'success',
          message: '删除成功!'
        })
        console.log(ids)
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    deleteBtnHandle(index, row) { // 行内删除按钮事件处理
      console.log(row.id)
      this.deletes([row.id])
    },
    delAllBtnHandle() { // 删除全部按钮事件处理
      const $this = this
      const length_ = this.multiple_selection.length
      if (length_ < 1) {
        $this.$message.error('请至少选择一项')
        return
      }
      var ids = []
      for (let i = 0; i < length_; i++) {
        ids.push($this.multiple_selection[i].id)
      }
      $this.multiple_selection = []
      this.deletes(ids)
    },
    editOkHandler() { // 编辑保存事件处理
      var res = this.$refs.inputsRef.allInputVerify()
      if (!res) {
        layer.msg('填写的信息有误')
        return
      }
      console.log('验证通过')
      var inputs = this.page_data.editInputs.inputs
      console.log(inputs)
      // 请求后台更新后
      this.$emit('editSaveAfter', inputs)
    },
    initDialogData(inputs, row) { // 初始化模态框内数据
      var $this = this
      inputs.forEach((val) => { // 设置编辑表单内的数据
        if (row[val.name] !== undefined) $this.$set(val, 'value', row[val.name]) // 避免清除已填写的内容
      })
    },
    editBtnHandle(index, row) { // 行内编辑按钮事件处理
      if (!this.page_data.editInputs) return
      this.edit_dialog_visible = true
      this.initDialogData(this.page_data.editInputs.inputs || [], row)
    },
    detailBtnHandle(row, column, cell) { // 行内查看详情事件处理 和 双击事件处理
      if (cell && cell.label === '操作') return
      if (!this.page_data.detailInputs) return
      this.detail_dialog_visible = true
      this.initDialogData(this.page_data.detailInputs.inputs || [], row)
    },
    currentChangeHandle(page) { // 分页改变时事件处理
      this.cur_page = page
      this.getData()
    },
    sizeChangeHandle(pageSize) { // pageSize改变时事件处理
      this.pageSize = pageSize
      this.cur_page = 1
      this.getData()
    },
    sortHandle(param) { // 排序事件处理 后台排序
      this.sort = param
      this.getData()
    },
    filterHandle(filters) { // 过滤事件处理  后台过滤
      for (var f in filters) {
        this.$set(this.filters, f, filters[f])
      }
      this.getData()
    },
    selectionChangeHandle(multiple_selection) { // 选中表格行事件处理
      this.multiple_selection = multiple_selection
    },
    modalToggleHandler(b) { // 模态框加特效
      document.getElementById('app').className = b ? 'mouhu' : ''
    }
  },
  watch: {
    controller(ctrl) {
      this.controller_ = ctrl
    },
    requestPrefix(prefix) {
      this.request_prefix = prefix
    }
  },
  created() {
    document.getElementById('app').className = '' // 创建的时候默认清除模糊效果
    const $this = this
    const test_url = 'static/baseTableData.json'// 测试时使用的数据
    $this.getData(false)
    get({ url: test_url }, res => {
      if (!res) {
        throw new Error('page_data is empty')
      }
      for (var key in res) {
        $this.$set($this.page_data, key, res[key])
        if (key === 'columns') {
          var arr = res.columns['columns']
          // 验证columns数据合法性
          if (!arr) throw new Error('page_data deficiency columns  deficiency columns key columns value')
          arr.forEach((d) => {
            if (d.filters) {
              $this.$set($this.filters, d.column, [])
            }
          })
        }
      }
      // 设置搜索默认选项
      var temp = $this.page_data['searchInputs'] || []
      if (temp.length > 0) {
        $this.$set($this.search, 'select', temp[0].name)
      }
      this.moreSearchClear()
    })
  }
}
</script>

<style scoped>
  .handle-box {
    padding: 1rem;
  }

  .el-message{
    margin-top: 200px;
  }

  .myHeader{
    min-height: 3.75rem;
    height: auto !important;
  }

  .topActionBar{
    min-height: 2.5rem;
    height: auto !important;
  }

  .moreSearch{
    min-height: 12rem;
    height: auto !important;
  }

  .search-input >>> .el-select{
    width: 6.25rem;
    font-size: 0.75rem;
  }

  .detailDialog{
    height: 96%;
    margin-top: 1%;
    filter: blur(0);
  }

  .detailDialog >>> .dialog-body{
    width: 100%;
    height: 100%;
    border: none;
  }

  .detailDialog >>> .el-dialog__header {
    height: 8%;
  }

  .detailDialog >>> .el-dialog__body {
    height: 85%;
    padding: 0.3125rem 0.625rem;
  }

  .detailDialog >>> .el-dialog__footer {
    position: absolute;
    right: 0;
    bottom: 0;
    height: 8%
  }

  .pagination >>> .el-pagination__sizes {
    float: left;
  }
  .el-table >>> .pitch-on {
    background: #EDF5FF;
  }
  .el-table >>> .warning-row {
    background: oldlace;
  }
  .el-table  >>> .success-row {
    background: #f0f9eb;
  }

  .pagination{
    margin: 1.25rem 0;
    text-align: right;
  }
</style>
